package com.beerandjesus.sportofkings.handicapper.dao.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.reflect.MethodSignature;
import org.apache.log4j.Logger;

import java.lang.reflect.Method;

/**
 * Date: Sep 8, 2012
 * Time: 3:24:43 PM
 */
public abstract class AbstractAnnotationAspect<T extends java.lang.annotation.Annotation> {
    protected T obtainAnnotation(ProceedingJoinPoint pjp, Class<T> clazz) {
        Signature sig = pjp.getSignature();
        Method meth = ((MethodSignature) sig).getMethod();
        T anno = meth.getAnnotation(clazz);
        if (anno == null) {
            // May be an interface call while annotation is on the
            // implementing class' method
            Class<?> realClass = pjp.getSourceLocation().getWithinType();
            Method realMethod;
            try {
                realMethod = realClass.getMethod(meth.getName(), meth.getParameterTypes());
            } catch (NoSuchMethodException e) {
                throw new RuntimeException(e);
            }
            anno = realMethod.getAnnotation(clazz);
            if (getLogger().isDebugEnabled()) {
                if (anno != null) {
                    getLogger().debug("Found annotation on implementation method "
                            + realMethod.getDeclaringClass().getCanonicalName() + "." + realMethod.getName());
                }
            }
            return anno;
        }
        if (getLogger().isDebugEnabled()) {
            getLogger().debug("Found annotation on called method "
                    + meth.getDeclaringClass().getCanonicalName() + "." + meth.getName());
        }
        return anno;
    }

    abstract Logger getLogger();
}
